﻿using Microsoft.Extensions.DependencyInjection;
using Sgr.Data;
using Sgr.Domain.Uow;
using Sgr.UPMS.Domain.Departments;
using Sgr.UPMS.Domain.Duties;
using Sgr.UPMS.Domain.Organizations;
using Sgr.UPMS.Domain.Roles;
using Sgr.UPMS.Domain.Users;
using Sgr;
using Sgr.Identity.Services;
using Sgr.Security.Permissions;

namespace Xunit.Sgr
{
    /// <summary>
    /// 测试数据初始化帮助类
    /// </summary>
    public class SeedDataHelper
    {
        #region 常量定义

        // 组织相关常量
        public const string ORG_CODE = "SGR_TEST_ORG_CODE";

        public const string IDENTIFICATION_CODE = "SGR_TEST_119";

        // 用户相关常量
        public const string USERNAME_ADMIN = "SgrTestAdmin";

        public const string USERNAME_CUSTOM = "SgrTestCustom";
        public const string PASSWORD = "1qaz@WSX";
        public const long USERID_CUSTOM = 132120263311;

        // 部门ID常量
        public const long DepartmentId01 = 6001;

        public const long DepartmentId02 = 6002;
        public const long DepartmentId03 = 6003;

        // 职务ID常量
        public const long DutyId01 = 7001;

        public const long DutyId02 = 7002;
        public const long DutyId03 = 7003;

        // 角色ID常量
        public const long RoleId01 = 8001;

        public const long RoleId02 = 8002;
        public const long RoleId03 = 8003;

        #endregion 常量定义

        /// <summary>
        /// 清理测试数据
        /// </summary>
        public static Task ClearDataAsync()
        {
            return Task.CompletedTask;
        }

        /// <summary>
        /// 初始化测试数据
        /// </summary>
        /// <param name="serviceProvider">服务提供者</param>
        public static async Task InitData(IServiceProvider serviceProvider)
        {
            using var scope = serviceProvider.CreateScope();

            // 获取必要的服务
            var services = GetRequiredServices(scope);

            using var uow = services.UnitOfWork.Begin();

            //// 初始化数据库种子数据
            //var databaseSeed = scope.ServiceProvider.GetRequiredService<IDatabaseSeed>();
            //await databaseSeed.SeedAsync();

            // 解析用户ID和组织ID
            var (userId, orgId) = GetUserAndOrgIds(services.CurrentUser);

            // 初始化基础数据
            await InitializeBaseData(services, userId, orgId);

            await uow.CommitAsync();
        }

        #region 私有辅助方法

        /// <summary>
        /// 获取所需服务
        /// </summary>
        private static (
            ICurrentUser CurrentUser,
            IUserManage UserManage,
            IRoleManage RoleManage,
            IEnumerable<IPermissionProvider> PermissionProviders,
            IUnitOfWorkManager UnitOfWork,
            IUserRepository UserRepository,
            IOrganizationRepository OrgRepository,
            IDutyRepository DutyRepository,
            IDepartmentRepository DeptRepository,
            IRoleRepository RoleRepository,
            IPasswordHashService PasswordHashService) GetRequiredServices(IServiceScope scope)
        {
            return (
                scope.ServiceProvider.GetRequiredService<ICurrentUser>(),
                scope.ServiceProvider.GetRequiredService<IUserManage>(),
                scope.ServiceProvider.GetRequiredService<IRoleManage>(),
                scope.ServiceProvider.GetRequiredService<IEnumerable<IPermissionProvider>>(),
                scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>(),
                scope.ServiceProvider.GetRequiredService<IUserRepository>(),
                scope.ServiceProvider.GetRequiredService<IOrganizationRepository>(),
                scope.ServiceProvider.GetRequiredService<IDutyRepository>(),
                scope.ServiceProvider.GetRequiredService<IDepartmentRepository>(),
                scope.ServiceProvider.GetRequiredService<IRoleRepository>(),
                scope.ServiceProvider.GetRequiredService<IPasswordHashService>()
            );
        }

        /// <summary>
        /// 获取用户ID和组织ID
        /// </summary>
        private static (long UserId, long OrgId) GetUserAndOrgIds(ICurrentUser currentUser)
        {
            _ = long.TryParse(currentUser.Id, out long userId);
            _ = long.TryParse(currentUser.OrgId, out long orgId);
            return (userId, orgId);
        }

        /// <summary>
        /// 初始化基础数据
        /// </summary>
        private static async Task InitializeBaseData(
            (ICurrentUser CurrentUser,
            IUserManage UserManage,
            IRoleManage RoleManage,
            IEnumerable<IPermissionProvider> PermissionProviders,
            IUnitOfWorkManager UnitOfWork,
            IUserRepository UserRepository,
            IOrganizationRepository OrgRepository,
            IDutyRepository DutyRepository,
            IDepartmentRepository DeptRepository,
            IRoleRepository RoleRepository,
            IPasswordHashService PasswordHashService) services,
            long userId,
            long orgId)
        {
            // 创建组织
            await CreateOrganization(services.OrgRepository, orgId);

            // 创建部门
            await CreateDepartments(services.DeptRepository, orgId);

            // 创建职务
            await CreateDuties(services.DutyRepository, orgId);

            // 创建角色
            await CreateRoles(services.RoleRepository, services.RoleManage, services.PermissionProviders, orgId);

            // 创建用户
            await CreateUsers(services.UserRepository, services.UserManage, services.PasswordHashService, userId, orgId);
        }

        /// <summary>
        /// 创建组织
        /// </summary>
        private static async Task CreateOrganization(IOrganizationRepository repository, long orgId)
        {
            var org = await repository.GetAsync(orgId);
            if (org == null)
            {
                org = new Organization(IDENTIFICATION_CODE, ORG_CODE, "staffSizeCode", "测试专用") { Id = orgId };
                await repository.InsertAsync(org);
            }
        }

        /// <summary>
        /// 创建部门
        /// </summary>
        private static async Task CreateDepartments(IDepartmentRepository repository, long orgId)
        {
            await CreateDepartment(repository, orgId, DepartmentId01);
            await CreateDepartment(repository, orgId, DepartmentId02);
            await CreateDepartment(repository, orgId, DepartmentId03);
        }

        /// <summary>
        /// 创建单个部门
        /// </summary>
        private static async Task CreateDepartment(IDepartmentRepository repository, long orgId, long deptId)
        {
            var entity = await repository.GetAsync(deptId);
            if (entity == null)
            {
                entity = new Department($"{deptId}_Core", $"{deptId}_NAME", 0, $"{deptId}_REMARK", orgId) { Id = deptId };
                await repository.InsertAsync(entity);
            }
        }

        /// <summary>
        /// 创建职务
        /// </summary>
        private static async Task CreateDuties(IDutyRepository repository, long orgId)
        {
            await CreateDuty(repository, orgId, DutyId01);
            await CreateDuty(repository, orgId, DutyId02);
            await CreateDuty(repository, orgId, DutyId03);
        }

        /// <summary>
        /// 创建单个职务
        /// </summary>
        private static async Task CreateDuty(IDutyRepository repository, long orgId, long dutyId)
        {
            var entity = await repository.GetAsync(dutyId);
            if (entity == null)
            {
                entity = new Duty($"{dutyId}_CODE", $"{dutyId}_NAME", 0, $"{dutyId}_REMARK", orgId) { Id = dutyId };
                await repository.InsertAsync(entity);
            }
        }

        /// <summary>
        /// 获取功能资源代码
        /// </summary>
        private static async Task<string[]> GetFuncResourceCodes(IEnumerable<IPermissionProvider> permissionProviders)
        {
            var funcResourceCodes = new List<string>();
            foreach (var provider in permissionProviders)
            {
                var funcPermissions = await provider.GetFunctionPermissionsAsync();
                funcResourceCodes.AddRange(funcPermissions.Select(fp => fp.Name));
            }
            return funcResourceCodes.ToArray();
        }

        /// <summary>
        /// 创建角色
        /// </summary>
        private static async Task CreateRoles(IRoleRepository repository, IRoleManage roleManage,
            IEnumerable<IPermissionProvider> permissionProviders, long orgId)
        {
            var funcResourceCodes = await GetFuncResourceCodes(permissionProviders);
            await CreateRole(repository, orgId, RoleId01, roleManage, funcResourceCodes);
            await CreateRole(repository, orgId, RoleId02, roleManage);
            await CreateRole(repository, orgId, RoleId03, roleManage);
        }

        /// <summary>
        /// 创建单个角色
        /// </summary>
        private static async Task CreateRole(IRoleRepository repository, long orgId, long roleId,
            IRoleManage roleManage, string[]? funcResourceCodes = null)
        {
            var entity = await repository.GetAsync(roleId);
            if (entity == null)
            {
                entity = await roleManage.CreateNewAsync($"{roleId}_NAME", orgId, 0, $"{roleId}_REMARK");
                entity.Id = roleId;
                entity.DifferenceUpdateFunctionalPermission(ResourceType.FunctionalPermission, funcResourceCodes);
                await repository.InsertAsync(entity);
            }
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        private static async Task CreateUsers(IUserRepository repository, IUserManage userManage,
            IPasswordHashService passwordHashService, long userId, long orgId)
        {
            // 创建管理员用户
            var adminUser = await repository.GetAsync(userId);
            if (adminUser == null)
            {
                adminUser = await userManage.CreateNewAsync(
                    USERNAME_ADMIN,
                    passwordHashService,
                    PASSWORD,
                    false,
                    orgId);
                adminUser.Id = userId;
                adminUser.DifferenceUpdateRoles(new[] { RoleId01 });
                await repository.InsertAsync(adminUser);
            }

            // 创建普通用户
            var customUser = await repository.GetAsync(USERID_CUSTOM);
            if (customUser == null)
            {
                customUser = await userManage.CreateNewAsync(
                    USERNAME_CUSTOM,
                    passwordHashService,
                    PASSWORD,
                    false, orgId);
                customUser.Id = USERID_CUSTOM;
                customUser.DifferenceUpdateDuties(new[] { DutyId01 });
                customUser.DifferenceUpdateRoles(new[] { RoleId02, RoleId03 });
                await repository.InsertAsync(customUser);
            }
        }

        #endregion 私有辅助方法
    }
}